package com.todo.strategy.online.application.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.todo.common.common.constants.BizConstants;
import com.todo.common.common.enums.BizErrorCodeEnum;
import com.todo.common.common.exception.BizException;
import com.todo.common.utils.StringUtils;
import com.todo.component.redis.RedisService;
import com.todo.strategy.common.constant.StrategyOnlineKeyBuild;
import com.todo.strategy.online.infrastructure.entity.po.WantSetPO;
import com.todo.strategy.online.infrastructure.repository.WantSetRepository;
import com.todo.strategy.online.application.convert.WantSetConvert;
import com.todo.strategy.online.application.entity.bo.WantSetBO;
import com.todo.strategy.online.application.service.WantRelationService;
import com.todo.strategy.online.application.service.WantSetService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * (WantSet)表服务实现类
 *
 * @author zhangwenxiang
 * @since 2024-03-04 00:19:50
 */
@Slf4j
@Service("wantSetService")
public class WantSetServiceImpl implements WantSetService {

    @Resource
    private WantSetRepository wantSetRepository;
    @Resource
    private WantRelationService wantRelationService;
    @Resource
    private RedisService redisService;

    @Override
    public Boolean insertWantSet(WantSetBO wantSetBO) {
        if (null == wantSetBO) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        if (wantSetBO.getStartPlanTime() == null || wantSetBO.getEndPlanTime() == null || wantSetBO.getStartPlanTime().after(wantSetBO.getEndPlanTime())) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "开始结束时间异常");
        }
        List<WantSetBO> wantSetBOList = queryWantSetByUserId(wantSetBO.getUserId());
        if (wantSetBOList.size() >= BizConstants.DEFAULT_MAX_WANT_SET_SIZE) {
            throw new BizException(BizErrorCodeEnum.RELATION_DATA_EXCESSIVE);
        }
        WantSetBO sameNameWantSet = wantSetBOList
                .stream()
                .filter(item -> item.getName().equals(wantSetBO.getName()))
                .findFirst()
                .orElse(null);
        if (sameNameWantSet != null) {
            throw new BizException(BizErrorCodeEnum.SUCCESS_EXIST, "当前集合名称已存在");
        }
        WantSetPO wantSetPO = WantSetConvert.converttoWantSetPO(wantSetBO);
        Boolean insertResult = wantSetRepository.insertWantSetPO(wantSetPO);
        if (insertResult) {
            String userListKey = StrategyOnlineKeyBuild.wantUserListKey(wantSetBO.getUserId());
            redisService.hSet(userListKey, String.valueOf(wantSetBO.getWantId()), JSONObject.toJSONString(wantSetBO));
        }
        return insertResult;
    }

    @Override
    public Boolean updateWantSet(WantSetBO wantSetBO) {
        if (null == wantSetBO || wantSetBO.getWantId() == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        if (wantSetBO.getStartPlanTime() == null || wantSetBO.getEndPlanTime() == null || wantSetBO.getStartPlanTime().after(wantSetBO.getEndPlanTime())) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "开始结束时间异常");
        }
        WantSetBO alreadyWantSetBO = queryWantSetById(wantSetBO.getWantId());
        if (alreadyWantSetBO == null) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR, "当前集合不存在");
        }
        //如果名称涉及调整
        if (!wantSetBO.getName().equals(alreadyWantSetBO.getName())) {
            List<WantSetBO> wantSetBOList = queryWantSetByUserId(wantSetBO.getUserId());
            if (wantSetBOList.size() >= BizConstants.DEFAULT_MAX_WANT_SET_SIZE) {
                throw new BizException(BizErrorCodeEnum.RELATION_DATA_EXCESSIVE);
            }
            WantSetBO sameNameWantSet = wantSetBOList
                    .stream()
                    .filter(item -> item.getName().equals(wantSetBO.getName()))
                    .findFirst()
                    .orElse(null);
            if (sameNameWantSet != null) {
                throw new BizException(BizErrorCodeEnum.SUCCESS_EXIST, "当前集合名称已存在");
            }
        }
        WantSetPO wantSetPO = WantSetConvert.converttoWantSetPO(wantSetBO);
        Boolean updateResult = wantSetRepository.updateWantSetPOById(wantSetPO);
        if (updateResult) {
            String userListKey = StrategyOnlineKeyBuild.wantUserListKey(wantSetBO.getUserId());
            redisService.hDel(userListKey, String.valueOf(wantSetBO.getWantId()));
        }
        return updateResult;
    }

    @Override
    public Boolean updateWantSetRelationCount(Long wantId, Integer relationCount) {
        if (wantId == null || wantId < 0 || relationCount == null || relationCount < 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        WantSetBO wantSetBO = queryWantSetById(wantId);
        if (wantSetBO == null) {
            throw new BizException(BizErrorCodeEnum.DATA_NOT_EXIST);
        }
        wantSetBO.setRelationCount(relationCount);
        WantSetPO wantSetPO = new WantSetPO();
        wantSetPO.setId(wantId);
        wantSetPO.setRelationCount(relationCount);
        Boolean updated = wantSetRepository.updateWantSetPOById(wantSetPO);
        if (updated) {
            String userListKey = StrategyOnlineKeyBuild.wantUserListKey(wantSetBO.getUserId());
            redisService.hDel(userListKey, String.valueOf(wantId));
        }
        return updated;
    }

    @Override
    @Transactional
    public Boolean removeWantSetById(Long id) {
        if (id == null || id < 0) {
            throw new BizException(BizErrorCodeEnum.PARAM_ERROR);
        }
        WantSetBO wantSetBO = queryWantSetById(id);
        if (wantSetBO == null) {
            log.info("WantSetService#removeWantSetById 删除我想去完成，根据主键id查询数据为空，默认成功 id：【{}】", id);
            return true;
        }
        Boolean updated = wantSetRepository.removeWantSetPOById(id);
        if (updated) {
            Boolean removed = wantRelationService.removeWantRelationByWantId(id);
            if (removed) {
                String userListKey = StrategyOnlineKeyBuild.wantUserListKey(wantSetBO.getUserId());
                redisService.del(userListKey);
            } else {
                throw new BizException(BizErrorCodeEnum.OPERATION_FAILED, "关联数据删除失败");
            }
        }
        return updated;
    }

    @Override
    public WantSetBO queryWantSetById(Long id) {
        if (id == null || id < 0) {
            return null;
        }
        String userListKey = StrategyOnlineKeyBuild.wantUserListKey(id);
        String cacheData = redisService.hGet(userListKey, String.valueOf(id));
        if (StringUtils.isNotBlank(cacheData)) {
            WantSetBO wantSetBO = JSONObject.parseObject(cacheData, WantSetBO.class);
            return wantSetBO;
        }
        WantSetPO wantSetPO = wantSetRepository.queryWantSetPOById(id);
        WantSetBO wantSetBO = WantSetConvert.converttoWantSetBO(wantSetPO);
        if (wantSetBO != null) {
            redisService.hSet(userListKey, String.valueOf(id), JSONObject.toJSONString(wantSetBO));
        }
        return wantSetBO;
    }

    @Override
    public List<WantSetBO> queryWantSetByUserId(Long userId) {
        if (userId == null || userId < 0) {
            return Collections.emptyList();
        }
        String userListKey = StrategyOnlineKeyBuild.wantUserListKey(userId);
        Map<String, String> cacheMap = redisService.hGetAll(userListKey);
        List<WantSetBO> result = new ArrayList<>();
        if (MapUtils.isNotEmpty(cacheMap)) {
            for (String key : cacheMap.keySet()) {
                WantSetBO wantSetBO = JSONObject.parseObject(cacheMap.get(key), WantSetBO.class);
                if (wantSetBO != null) {
                    result.add(wantSetBO);
                }
            }
            return result;
        }
        List<WantSetPO> wantSetPOList = wantSetRepository.queryWantSetPOByUserId(userId);
        if (wantSetPOList == null) {
            log.warn("WantSetService#queryWantSetByUserId 根据用户id查询数据为空，默认返回空列表 userId：【{}】", userId);
            return Collections.emptyList();
        }
        List<WantSetBO> collect = wantSetPOList.stream().map(WantSetConvert::converttoWantSetBO).collect(Collectors.toList());
        for (WantSetBO wantSetBO : collect) {
            redisService.hSet(userListKey, String.valueOf(wantSetBO.getWantId()), JSONObject.toJSONString(wantSetBO));
        }
        return collect;
    }

    @Override
    @Transactional
    public Boolean removeWantSetByIdList(List<Long> wantIdList) {
        if (CollectionUtils.isEmpty(wantIdList)) {
            return true;
        }
        for (Long wantId : wantIdList) {
            removeWantSetById(wantId);
        }
        log.info("WantSetService#removeWantSetByIdList 批量删除完成，入参：【{}】", JSONObject.toJSONString(wantIdList));
        return true;
    }

}
